#include "syntax_tree.h"
#include "semantic_analyzer.h"
#include "main_container.h"
#include "errors_warnings.h"

extern MainContainer * CompilerData;


//SemanticsNamespace * GatherFromNamespace(SyntaxTreeNode * nodeClass, int parentContext);
//Productions:
//Gr_MainDefinition__NamespaceDefinition, 
//Gr_NamespaceDefinition__namespace_Name_spLCBrac_UsingDirectives_FileBody_spRCBrac
SemanticsNamespace * SemanticAnalyzer::GatherFromNamespace(SyntaxTreeNode * nodeNamespace, int parentContext)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromNamespace");
#endif

	SemanticsNamespace * sn;

	if(nodeNamespace->LexUnitID == -1 && nodeNamespace->Production == Gr_MainDefinition__NamespaceDefinition)
	{
		// recursive call for different syntax tree
		SyntaxTreeNode * namespaceDefinitionNode = nodeNamespace->Nodes->GetData(0);
		sn = GatherFromNamespace(namespaceDefinitionNode, parentContext);
	}
	else if(nodeNamespace->LexUnitID == -1 && nodeNamespace->Production == Gr_NamespaceDefinition__namespace_Name_spLCBrac_UsingDirectives_FileBody_spRCBrac)
	{
		sn = new SemanticsNamespace();
		SyntaxTreeNode * nameNode = nodeNamespace->Nodes->GetData(1);
		SyntaxTreeNode * usingDirectivesNode = nodeNamespace->Nodes->GetData(3);
		SyntaxTreeNode * fileBodyNode = nodeNamespace->Nodes->GetData(4);
		
		sn->Name = GatherFromNameNode(nameNode);			
		
		int currentContextID = SaveContext(GetCurrentContext(usingDirectivesNode), parentContext);
			
		GatherFromFileBody(fileBodyNode, currentContextID, sn);
	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(nodeNamespace->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromNamespace");
#endif
	return sn;
}



//SemanticsEnum * GatherFromEnum(SyntaxTreeNode * nodeClass, int parentContext);
//Productions:
//Gr_MainDefinition__EnumDefinition, 
//Gr_EnumDefinition__enum_NAME_spLCBrac_EnumNames_spRCBrac
SemanticsEnum * SemanticAnalyzer::GatherFromEnum(SyntaxTreeNode * nodeEnum, int parentContext)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromEnum");
#endif

	SemanticsEnum * se;

	if(nodeEnum->Production == Gr_MainDefinition__EnumDefinition || nodeEnum->Production == Gr_ClassBody__EnumDefinition)
	{
		SyntaxTreeNode * enumDefinitionNode = nodeEnum->Nodes->GetData(0);
		se = GatherFromEnum(enumDefinitionNode, parentContext);
	}
	else if(nodeEnum->Production == Gr_EnumDefinition__enum_NAME_spLCBrac_EnumNames_spRCBrac)
	{
		se = new SemanticsEnum();
		SyntaxTreeNode * nameNode = nodeEnum->Nodes->GetData(1);
		SyntaxTreeNode * enumNamesNode = nodeEnum->Nodes->GetData(3);

		se->Name = GatherFromNameNode(nameNode);
		se->Enums = GatherFromEnumMembersNode(enumNamesNode);
	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(nodeEnum->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromEnum");
#endif
	return se;
}



//<enum_names>	~	NAME <enum_names_add>
//<name_comma_add>	~	, NAME
//<enum_names_add>	~	<name_comma_add> <enum_names_add>
//<enum_names_add>	~

/*
GenericTable<int> * SemanticAnalyzer::GatherFromEnumMembersNode(SyntaxTreeNode * enumNamesNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromEnumMembersNode");
#endif
	
	GenericTable<int> * enumNames;
	enumNames = new GenericTable<int>();

	if(enumNamesNode->LexUnitID == -1 && enumNamesNode->Production == Gr_EnumNames__NAME_EnumNamesAdd)
	{
		//<enum_names>	~	NAME <enum_names_add>
		SyntaxTreeNode *enumName = enumNamesNode->Nodes->GetData(0);
		SyntaxTreeNode *enumNamesAddNode = enumNamesNode->Nodes->GetData(1);

		// add lexic unit to enumNames table
		int * tempEnumName = new int;
		*tempEnumName = (CompilerData->Units->GetLexicUnit(enumName->LexUnitID)).subtype;
		enumNames->Add(tempEnumName);

		for(int i = 1; i < enumNamesAddNode->Nodes->GetCount(); i++)
		{
			//<enum_names_add>	~	<name_comma_add> <enum_names_add>
			SyntaxTreeNode * nameCommaAdd = enumNamesNode->Nodes->GetData(i);
			
			if(nameCommaAdd == NULL)
			{
				break;
			}

			if(nameCommaAdd->LexUnitID == -1 && nameCommaAdd->Production == Gr_EnumNamesAdd__epsilon)
			{
				break;
			}

			//<name_comma_add>	~	, NAME
			SyntaxTreeNode * enumNameMember = nameCommaAdd->Nodes->GetData(1);

			if(enumNameMember == NULL)
			{
				break;
			}
			
			//??? 
			// add lexic unit to enumNames table
			tempEnumName = new int;
			*tempEnumName = (CompilerData->Units->GetLexicUnit(enumNameMember->LexUnitID)).subtype;
			enumNames->Add(tempEnumName);
		}
	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(enumNamesNode->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}


#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromEnumMembersNode");
#endif
	return enumNames;
}
*/


GenericTable<int> * SemanticAnalyzer::GatherFromEnumMembersNode(SyntaxTreeNode * enumNamesNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromEnumMembersNode");
#endif
	int i;
	GenericTable<int> * enumNames;
	enumNames = new GenericTable<int>();

	if(enumNamesNode->LexUnitID == -1 && enumNamesNode->Production == Gr_EnumNames__NAME_EnumNamesAdd)
	{
		//<enum_names>	~	NAME <enum_names_add>
		SyntaxTreeNode *enumName = enumNamesNode->Nodes->GetData(0);
		SyntaxTreeNode *enumNamesAddNode = enumNamesNode->Nodes->GetData(1);




		// add lexic unit to enumNames table
		int * tempEnumName = new int;
		*tempEnumName = (CompilerData->Units->GetLexicUnit(enumName->LexUnitID)).subtype;
		enumNames->Add(tempEnumName);

		for(i = 0; i < enumNamesAddNode->Nodes->GetCount(); i++)
		{
			//<enum_names_add>	~	<name_comma_add> <enum_names_add>
			SyntaxTreeNode * nameCommaAdd = enumNamesAddNode->Nodes->GetData(i);

			if(nameCommaAdd == NULL)
			{
				break;
			}

			if(nameCommaAdd->LexUnitID == -1 && nameCommaAdd->Production == Gr_EnumNamesAdd__epsilon)
			{
				break;
			}

			//<name_comma_add>	~	, NAME
			SyntaxTreeNode * enumNameMember = nameCommaAdd->Nodes->GetData(1);

			if(enumNameMember == NULL)
			{
				break;
			}
			
			// add lexic unit to enumNames table
			tempEnumName = new int;
			*tempEnumName = (CompilerData->Units->GetLexicUnit(enumNameMember->LexUnitID)).subtype;
			enumNames->Add(tempEnumName);
		}
	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(enumNamesNode->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}


#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromEnumMembersNode");
#endif
	return enumNames;
}

//SemanticsModel * GatherFromModel(SyntaxTreeNode * nodeModel, int parentContext);
//Productions:
//Gr_MainDefinition__ModelDefinition, 
//Gr_ModelDefinition__ModelMod_model_Name_spLPar_Arguments_spRPar_ModelDefinitionIn_ModelDefinitionOut_spLCBrac_ModelBody_spRCBrac
SemanticsModel * SemanticAnalyzer::GatherFromModel(SyntaxTreeNode * nodeModel, int parentContext)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromModel");
#endif

	SemanticsModel * sm;

	if(nodeModel->LexUnitID == -1 && nodeModel ->Production == Gr_MainDefinition__ModelDefinition)
	{
		SyntaxTreeNode * modelDefinitionNode = nodeModel->Nodes->GetData(0);
		sm = GatherFromModel(modelDefinitionNode, parentContext);
	}
	else if(nodeModel->LexUnitID == -1 && nodeModel->Production == Gr_ModelDefinition__ModelMod_model_Name_spLPar_Parameters_spRPar_ModelDefinitionIn_ModelDefinitionOut_spLCBrac_ModelBody_spRCBrac)
	{
		sm = new SemanticsModel();

		SyntaxTreeNode * modelModNode = nodeModel->Nodes->GetData(0);
		SyntaxTreeNode * nameNode = nodeModel->Nodes->GetData(2);
		SyntaxTreeNode * parametersNode = nodeModel->Nodes->GetData(4);
		SyntaxTreeNode * modelDefinitionInNode = nodeModel->Nodes->GetData(6);
		SyntaxTreeNode * modelDefinitionOutNode = nodeModel->Nodes->GetData(7);
		SyntaxTreeNode * modelBodyNode = nodeModel->Nodes->GetData(9);
		
		if(modelModNode->LexUnitID == -1 && modelModNode->Production == Gr_ModelMod__public)
		{
			// <model_mod>	~	public
			sm->ModifierPublic = true;
		}
		else if(modelModNode->LexUnitID == -1 && modelModNode->Production == Gr_ModelMod__private)
		{
			// <model_mod>	~	private
			sm->ModifierPrivate = true;
		}

		sm->Name = GatherFromNameNode(nameNode);
		
		sm->Parameters = GatherParameters(parametersNode);

		
		// <model_definition_in>	~	in ( <label_list> )
		if(modelDefinitionInNode->LexUnitID == -1 && modelDefinitionInNode->Production == Gr_ModelDefinitionIn__in_spLPar_LabelList_spRPar)
		{
			SyntaxTreeNode * labelsNode = modelDefinitionInNode->Nodes->GetData(2);
			if(labelsNode->Production == Gr_LabelList__default_Labels)
			{
				sm->HasDefaultInLabel = true;
			}

			sm->LabelsIn = GatherLabels(labelsNode);
		}

		// <model_definition_out>	~	out ( <label_list> )
		if(modelDefinitionOutNode->LexUnitID == -1 && modelDefinitionOutNode->Production == Gr_ModelDefinitionOut__out_spLPar_LabelList_spRPar)
		{
			SyntaxTreeNode * labelsNode = modelDefinitionOutNode->Nodes->GetData(2);
			if(labelsNode->Production == Gr_LabelList__default_Labels)
			{
				sm->HasDefaultOutLabel = true;
			}

			sm->LabelsOut = GatherLabels(labelsNode);
		}


		//<model_body> ~ **** <using_directives> <model_define> <model_structure>
		if(modelBodyNode->LexUnitID == -1 && modelBodyNode->Production == Gr_ModelBody__UsingDirectives_ModelDefine_ModelStructure)
		{
			SyntaxTreeNode * usingDirectivesNode = modelBodyNode->Nodes->GetData(0);
			SyntaxTreeNode * modelDefineNode = modelBodyNode->Nodes->GetData(1);
			SyntaxTreeNode * modelStructureNode = modelBodyNode->Nodes->GetData(2);

			int currentContextID = SaveContext(GetCurrentContext(usingDirectivesNode), parentContext);

			sm->Definition = GatherFromModelBodyDefine(modelDefineNode,currentContextID);
			sm->Structure = GatherFromModelStructure(modelStructureNode,currentContextID);
		}
		else
		{
			// report error
			CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(nodeModel->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
		}

	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(nodeModel->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}


#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromModel");
#endif
	return sm;
}



//<label_list>	~	
//<label_list>	~	default <labels>
//<label_list>	~	NAME <labels>
//<labels>	~	<comma_label> <labels>
//<labels>	~	
//<comma_label>	~	, NAME
GenericTable<int> * SemanticAnalyzer::GatherLabels(SyntaxTreeNode * labelListNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherLabels");
#endif

	GenericTable<int> * labels = new GenericTable<int>();

	if(labelListNode->Production == Gr_LabelList__default_Labels || labelListNode->Production == Gr_LabelList__NAME_Labels)
	{
		//<label_list>	~	default <labels>
		// -> nothing special needed
		if(labelListNode->Production == Gr_LabelList__NAME_Labels)
		{
			//<label_list>	~	NAME <labels>
			// NAME will be added to the table
			
			SyntaxTreeNode * labelNameNode = labelListNode->Nodes->GetData(0);

			GenericTable<int> * tempTable = GatherFromNameNode(labelNameNode);
			int * tempName = new int;
			* tempName = * tempTable->GetData(0);
			delete tempTable;

			labels->Add(tempName);
		}

		SyntaxTreeNode * labelsNode = labelListNode->Nodes->GetData(1);

		for(int i=0; i < labelsNode->Nodes->GetCount(); i++)
		{
			SyntaxTreeNode * comaLabel = labelsNode->Nodes->GetData(i);
			
			//<comma_label>	~	, NAME
			SyntaxTreeNode * labelNameNode2 = comaLabel->Nodes->GetData(1);
			
			GenericTable<int> * tempTable = GatherFromNameNode(labelNameNode2);
			int * tempName = new int;
			* tempName = * tempTable->GetData(0);
			delete tempTable;

			labels->Add(tempName);
		}

	}
	else if(labelListNode->LexUnitID == -1 && labelListNode->Production == Gr_LabelList__epsilon)
	{
		//<label_list>	~	
		// -> do nothing

#ifdef TRACE
		CompilerData->LogTrace->ReportEntry("GatherLabels");
#endif
		return labels;
	}
	else
	{

	}


#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherLabels");
#endif

	return labels;
}




//<parameters>	~	<parameter> <parameters_add>
//<parameters>	~
//<parameters_add>	~	<parameter_comma_add> <parameters_add>
//<parameters_add>	~
//<parameter_comma_add>	~	, <parameter>

GenericTable<SemanticsMethodParameter> * SemanticAnalyzer::GatherParameters(SyntaxTreeNode * parametersNode)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherParameters");
#endif

	GenericTable<SemanticsMethodParameter> * parameters = new GenericTable<SemanticsMethodParameter>();


	if(parametersNode->LexUnitID == -1 && parametersNode->Production == Gr_Parameters__Parameter_ParametersAdd)
	{
		//<parameters>	~	<parameter> <parameters_add>
		parameters->Add(ReadMethodParameter(parametersNode->Nodes->GetData(0)));
		SyntaxTreeNode *parametersAddNode = parametersNode->Nodes->GetData(1);

		//<parameters_add>	~	<parameter_comma_add> <parameters_add>
		for(int i=0; i < parametersAddNode->Nodes->GetCount(); i++)
		{
			SyntaxTreeNode * parameterCommaAddNode = parametersAddNode->Nodes->GetData(i);
			
			//<parameter_comma_add>	~	, <parameter>
			SyntaxTreeNode * parameterNode = parameterCommaAddNode->Nodes->GetData(1);
			
			// gets the Parameter
			parameters->Add(ReadMethodParameter(parameterNode));
		}

	}
	else if(parametersNode->LexUnitID == -1 && parametersNode->Production == Gr_Parameters__epsilon)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportEntry("GatherParameters");
#endif
		return parameters;
	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(parametersNode->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}

#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherParameters");
#endif
	return parameters;
}





//SemanticsModelBodyDefine * GatherFromModelBodyDefine(SyntaxTreeNode * modelDefineNode, int parentContext);
//Productions:
//Gr_ModelDefine__define_spLCBrac_DefineBodyStatements_spRCBrac, 
//Gr_ModelDefine__epsilon, ...

//<define_body_statements> ~ <define_body_statement> <define_body_statements>
//<define_body_statements> ~ 
//<define_body_statement>	~	<field_definition>
//<define_body_statement>	~	<property_definition>
//<define_body_statement>	~	<method_definition>
//<define_body_statement>	~	<enum_definition>

SemanticsModelBodyDefine * SemanticAnalyzer::GatherFromModelBodyDefine(SyntaxTreeNode * modelDefineNode, int parentContext)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromModelBodyDefine");
#endif

	SemanticsModelBodyDefine * smbd = new SemanticsModelBodyDefine();
	
	if(modelDefineNode->LexUnitID == -1 && modelDefineNode->Production == Gr_ModelDefine__define_spLCBrac_DefineBodyStatements_spRCBrac)
	{
		// DefineBodyStatements
		SyntaxTreeNode * defineBodyStatements = modelDefineNode->Nodes->GetData(2);
		
		for(int i=0; i < defineBodyStatements->Nodes->GetCount(); i++)
		{
			SyntaxTreeNode * defineBodyStatementNode = defineBodyStatements->Nodes->GetData(i);
			
			if(defineBodyStatementNode->LexUnitID == -1 && defineBodyStatementNode->Production == Gr_DefineBodyStatement__EnumDefinition)
			{
				smbd->Enums->Add(GatherFromEnum(defineBodyStatementNode->Nodes->GetData(0),parentContext));
			}
			else if(defineBodyStatementNode->LexUnitID == -1 && defineBodyStatementNode->Production == Gr_DefineBodyStatement__FieldDefinition)
			{
				smbd->Fields->Add(GatherFromField(defineBodyStatementNode->Nodes->GetData(0),parentContext));
			}
			else if(defineBodyStatementNode->LexUnitID == -1 && defineBodyStatementNode->Production == Gr_DefineBodyStatement__MethodDefinition)
			{
				smbd->Methods->Add(GatherFromMethod(defineBodyStatementNode->Nodes->GetData(0),parentContext));
			}
			else if(defineBodyStatementNode->LexUnitID == -1 && defineBodyStatementNode->Production == Gr_DefineBodyStatement__PropertyDefinition)
			{
				smbd->Properties->Add(GatherFromProperty(defineBodyStatementNode->Nodes->GetData(0),parentContext));
			}
			else
			{
				// report error
				CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(defineBodyStatementNode->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
			}

		}


	}
	else if(modelDefineNode->Production == Gr_ModelDefine__epsilon)
	{
		// do nothing... it's epsilon :)
	}
	else
	{
		// report error
		CompilerData->ErrorWarningReport->ReportError(&CompilerData->Units->GetLexicUnit(modelDefineNode->LexUnitID), ERR_SEM_GENERIC_SEMANTIC_ERROR);
	}


#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromModelBodyDefine");
#endif

	return smbd;
}




//SemanticsModelStructure * GatherFromModelStructure(SyntaxTreeNode * modelStructureNode, int parentContext);
//Productions:
//Gr_ModelStructure__LabelGpssBlock_ModelStructure, 
//Gr_ModelStructure__epsilon

SemanticsModelStructure * SemanticAnalyzer::GatherFromModelStructure(SyntaxTreeNode * modelStructureNode, int parentContext)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("GatherFromModelStructure");
#endif

	SemanticsModelStructure * sms;

	sms = new SemanticsModelStructure();
	
	for(int i = 0; i < modelStructureNode->Nodes->GetCount(); i++)
	{
		sms->Blocks->Add(ReadModelBlock( modelStructureNode->Nodes->GetData(i) ));
	}


#ifdef TRACE
	CompilerData->LogTrace->ReportExit("GatherFromModelStructure");
#endif

	return sms;
}




/*
SemanticsModelBlock * SemanticAnalyzer::ReadModelBlock(SyntaxTreeNode * modelBlockNode); // kreativan posao :)
Productions:
Gr_LabelGpssBlock__BlockLabels_GpssBlock, 
Gr_BlockLabels__epsilon, 
Gr_BlockLabels__BlockLabel_BlockLabels, 
Gr_BlockLabel__NAME_spColon, 
Gr_BlockLabel__NAME_spPer_NAME_spColon, 
Gr_GpssBlock__****** 

*/
SemanticsModelBlock * SemanticAnalyzer::ReadModelBlock(SyntaxTreeNode * modelBlockNode)
{
	SemanticsModelBlock *smb = new SemanticsModelBlock();

	if( modelBlockNode->Production == Gr_LabelGpssBlock__BlockLabels_GpssBlock ){
		
		SyntaxTreeNode * blockLabels = modelBlockNode->Nodes->GetData(0);
		SyntaxTreeNode * gpssBlock = modelBlockNode->Nodes->GetData(1);
		
		smb->Labels = ReadModelBlockLabels(blockLabels);

		switch(gpssBlock->Production){
			case Gr_GpssBlock__AdvanceBlock:
				smb->BlockType = ModBlockAdvance;
				break;
			case Gr_GpssBlock__ArriveBlock:
				smb->BlockType = ModBlockArrive;
				break;
			case Gr_GpssBlock__CreateBlock:
				smb->BlockType = ModBlockCreate;
				break;
			case Gr_GpssBlock__DepartBlock:
				smb->BlockType = ModBlockDepart;
				break;
			case Gr_GpssBlock__EnterBlock:
				smb->BlockType = ModBlockEnter;
				break;
			case Gr_GpssBlock__ExecuteBlock:
				smb->BlockType = ModBlockExecute;
				break;
			case Gr_GpssBlock__GatherBlock:
				smb->BlockType = ModBlockGather;
				break;
			case Gr_GpssBlock__GenerateBlock:
				smb->BlockType = ModBlockGenerate;
				break;
			case Gr_GpssBlock__GotoBlock:
				smb->BlockType = ModBlockGoto;
				break;
			case Gr_GpssBlock__IfBlock:
				smb->BlockType = ModBlockIf;
				break;
			case Gr_GpssBlock__InqueueBlock:
				smb->BlockType = ModBlockInqueue;
				break;
			case Gr_GpssBlock__JoinGroupBlock:
				smb->BlockType = ModBlockJoinGroup;
				break;
			case Gr_GpssBlock__LeaveBlock:
				smb->BlockType = ModBlockLeave;
				break;
			case Gr_GpssBlock__LeaveGroupBlock:
				smb->BlockType = ModBlockLeaveGroup;
				break;
			case Gr_GpssBlock__ModelInstanceBlock:
				smb->BlockType = ModBlockModelInstance;
				break;
			case Gr_GpssBlock__OutqueueBlock:
				smb->BlockType = ModBlockOutqueue;
				break;
			case Gr_GpssBlock__ReleaseBlock:
				smb->BlockType = ModBlockRelease;
				break;
			case Gr_GpssBlock__SeizeBlock:
				smb->BlockType = ModBlockSeize;
				break;
			case Gr_GpssBlock__SplitBlock:
				smb->BlockType = ModBlockSplit;
				break;
			case Gr_GpssBlock__TerminateBlock:
				smb->BlockType = ModBlockTerminate;
				break;
			case Gr_GpssBlock__WaitBlock:
				smb->BlockType = ModBlockWait;
				break;
			default:
				//ERROR - unknown block
				break;
		}
		
	}
	else
	{
		//ERROR
	}
	

	return smb;

}

GenericTable<int> * SemanticAnalyzer::ReadModelBlockLabels(SyntaxTreeNode * modelBlockLabelsNode)
{
	#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("ReadModelBlockLabels");
	#endif

	GenericTable<int> *blockLabels;
	blockLabels = new GenericTable<int>();

	if(modelBlockLabelsNode->Production == Gr_BlockLabels__BlockLabel_BlockLabels)
	{
		for(int i=0; i < modelBlockLabelsNode->Nodes->GetCount(); i++)
		{
			SyntaxTreeNode * blockLabelNode = modelBlockLabelsNode->Nodes->GetData(i);
			
			// gets the name
			SyntaxTreeNode * labelName = modelBlockLabelsNode->Nodes->GetData(0);
			
			// add lexic unit to enumNames table
			//GatherFromNameNode(labelName)
			int * tempLabel = new int;
			* tempLabel = (CompilerData->Units->GetLexicUnit(labelName->LexUnitID)).subtype;
			blockLabels->Add(tempLabel);
		}
	}
	else
	{
		//ERROR
	}

	#ifdef TRACE
		CompilerData->LogTrace->ReportExit("ReadModelBlockLabels");
	#endif

	return blockLabels;
}